﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YasharEl.Infrastructure.ApplicationModel.Bootstrap.Configuration;
using YasharEl.Infrastructure.ApplicationModel.Modularity.Bootstrap;
using YasharEl.Infrastructure.Diagnostics.Logging;
using YasharEl.Infrastructure.WorkflowModel;
using YasharEl.Infrastructure.WorkflowModel.Configuration;
using YasharEl.Infrastructure.WorkflowModel.Management;

namespace YasharEl.Infrastructure.ApplicationModel.Bootstrap.Extensions
{
    public class WorkflowModelBootstrapperExtension : ModuleComponentBootstrappingExtension, IConsumeConfigurationSection
    {
        #region Fields

        private IWorkflowManagementService workflowManagementService;

        #endregion

        #region Properties

        public WorkflowModelConfig WorkflowModelConfigSection { get; private set; }

        #endregion

        #region BaseComplexBootstrappingExtension Abstract Overrides

        public override string Describe()
        {
            return "Extension which configure and start workflow cross cutting aspects such as persistance, unhandled exception handling, extensions and more.";
        }

        #endregion

        #region IConsumeConfigurationSection Implementations

        public void Apply(ConfigurationSection section)
        {
            WorkflowModelConfigSection = section as WorkflowModelConfig;
        }

        #endregion

        #region BaseComplexBootstrappingExtension Virtual Overrides

        public override void Configure()
        {
            try
            {
                Logger.Debug("Configuring workflow model...");

                if (WorkflowModelConfigSection == null)
                    throw new InvalidSystemConfigurationException("Workflow model cross cutting feature requested but not correctly configured. Check you config files.");

                #region Configuring WorkflowCompletionBehavior

                Logger.Debug("Configuring WorkflowCompletionBehavior : {0}", WorkflowModelConfigSection.WorkflowCompletionBehavior.WorkflowCompletionHandlerType);

                Container.DependencyRegistrar.Register(
                    typeof(IWorkflowCompletionHandler),
                    WorkflowModelConfigSection.WorkflowCompletionBehavior.WorkflowCompletionHandlerType,
                    true
                );

                Logger.Debug("WorkflowCompletionBehavior : {0} registered as singleton and configured...", WorkflowModelConfigSection.WorkflowCompletionBehavior.WorkflowCompletionHandlerType);

                #endregion

                #region Configuring IWorkflowDefinitionLoader

                Logger.Debug("Configuring IWorkflowDefinitionLoader : {0}", WorkflowModelConfigSection.WorkflowDefinitionLoaderType);

                Container.DependencyRegistrar.Register(
                    typeof(IWorkflowDefinitionLoader),
                    WorkflowModelConfigSection.WorkflowDefinitionLoaderType
                );

                Logger.Debug("IWorkflowDefinitionLoader : {0} registered and configured...", WorkflowModelConfigSection.WorkflowDefinitionLoaderType);

                #endregion

                Container.DependencyRegistrar.Register<WorkflowModelConfig>(WorkflowModelConfigSection, ModuleName, true);

                workflowManagementService = new DefaultWorkflowManagementService(
                    Container.DependencyResolver.Resolve<ILogger<DefaultWorkflowManagementService>>(),
                    Container.DependencyResolver,
                    WorkflowModelConfigSection);

                Container.DependencyRegistrar.Register<IWorkflowManagementService>(
                    workflowManagementService, true
                );

                Logger.Debug("IWorkflowManagementService regsitered...");

                Container.DependencyRegistrar.Register<IWorkflowOwnershipManagementService>(
                    workflowManagementService, true
                );

                Logger.Debug("IWorkflowOwnershipManagementService regsitered...");
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error occurred during configuring workflow model of module {0}.", ModuleName);
                throw;
            }
        }

        public override void Start()
        {
            base.Start();

            Logger.Debug("Starting workflow model...");

            try
            {
                workflowManagementService.Start();
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error occurred during starting workflow model of module {0}.", ModuleName);
                throw;
            }
        }

        public override void Shutdown()
        {
            base.Shutdown();

            Logger.Debug("Shutdown workflow model...");

            try
            {
                workflowManagementService.Dispose();
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "Error occurred during shutdown workflow model of module {0}.", ModuleName);
                throw;
            }
        }

        #endregion

        #region ModuleComponentBootstrappingExtension Overrides

        public override string SectionName
        {
            get { return WorkflowModelConfig.WorkflowModelConfigDefaultSectionName; }
        }

        #endregion
    }
}
